// $Id: eos.cpp 69 2004-11-18 10:18:04Z jonas $
#include "eos.h"
//#include "node.h"
#include "network.h"
#include "filehandler.h"
#include "partitionizer.h"
#include "loghandler.h"
#include "clock.h"
#include "distributions.h"
//using namespace std;
#include <unistd.h>	// DEBUG: For the sleep-function to simulate simulation :-)
#include <iostream>

/**
 * @todo Write documentation
 * @todo Document all parameters!
 */
Eos::Eos(const char *scenario, unsigned int randomSeed, unsigned int iterationCount, unsigned int nodeCount, int fileCount, unsigned int nodeFileStoreLimit, unsigned int nodeRoutingTableLimit, unsigned int requestHopsToLive, unsigned int insertHopsToLive, float requestProbability, float insertProbability)
	: m_scenario(scenario), m_randomSeed(randomSeed), m_iterationCount(iterationCount), m_nodeCount(nodeCount), m_fileCount(fileCount), m_nodeFileStoreLimit(nodeFileStoreLimit), m_nodeRoutingTableLimit(nodeRoutingTableLimit), m_requestHopsToLive(requestHopsToLive), m_insertHopsToLive(insertHopsToLive), m_requestProbability(requestProbability), m_insertProbability(insertProbability)
{
}

/**
 * Clear up all memory we allocated at the init proc.
 * @todo Make *sure* that we are deleteing everything that we are creating in init (if nobody else does!)
 */
Eos::~Eos()
{
	// Delete network
	delete m_network;

	// Delete all nodes
	for (list<Node *>::iterator node=m_nodes.begin(); node!=m_nodes.end(); node++) {
		delete *node;
	}
	m_nodes.clear();

	// Delete the distributions used
	delete m_distributions;

	// TODO: Delet all file handlers
	//delete m_fileHandler;

	// Delete the partitionizer used
	delete m_partitionizer;
}

/**
 * This is the core of the simulation. This method call all nodes execute
 * methods and make sure that the network transfers all files. The clock also
 * advances in each step.
 */
void Eos::simulate()
{
	LogHandler::getInstance()->eos_simulate_start((void *)this);

	//sleep(1); // DEBUG
	for (unsigned int i=0; i<m_iterationCount; i++) {
		for (list<Node *>::iterator node=m_nodes.begin(); node!=m_nodes.end(); node++) {
			(*node)->execute();
		}

		m_network->transfer();
		Clock::getInstance()->tick();
// cout << endl << "----- NEW TICK -----" << endl << endl;
	}

	LogHandler::getInstance()->eos_simulate_stop((void *)this);
}

/**
 * Add a FileHandler to a list so that they can be deleted when the simulation is over
 * @param fileHandler Pointer to the FileHandler to add.
 */
FileHandler *Eos::registerFileHandler(FileHandler *fileHandler)
{
	m_fileHandlers.push_back(fileHandler);
	return fileHandler;
}

/**
 * Sets all unset settings and lets previously set settings override
 * @todo Write complete doc
 */
void Eos::setSettings(unsigned int iterationCount, unsigned int nodeCount, int fileCount, unsigned int nodeFileStoreLimit, unsigned int nodeRoutingTableLimit, unsigned int requestHopsToLive, unsigned int insertHopsToLive, float requestProbability, float insertProbability)
{
	if(m_iterationCount){
		cout << "Simulation duration overridden." << endl;
	}
	else{
		m_iterationCount = iterationCount;
	}

	if(m_nodeCount){
		cout << "Network size overridden." << endl;
	}
	else{
		m_nodeCount = nodeCount;
	}

	if(m_fileCount!=-1){
		cout << "Initial file count overridden." << endl;
	}
	else{
		m_fileCount = fileCount;
	}

	if(m_nodeFileStoreLimit){
		cout << "File store max size overridden." << endl;
	}
	else{
		m_nodeFileStoreLimit = nodeFileStoreLimit;
	}

	if(m_nodeRoutingTableLimit){
		cout << "Routing table max size overridden." << endl;
	}
	else{
		m_nodeRoutingTableLimit = nodeRoutingTableLimit;
	}

	if(m_requestHopsToLive){
		cout << "Request Hops-To-Live overridden." << endl;
	}
	else{
		m_requestHopsToLive = requestHopsToLive;
	}

	if(m_insertHopsToLive){
		cout << "Insert Hops-To-Live  overridden." << endl;
	}
	else{
		m_insertHopsToLive = insertHopsToLive;
	}

	if(m_requestProbability>=0){
		cout << "Request probability overridden." << endl;
	}
	else{
		m_requestProbability = requestProbability;
	}

	if(m_insertProbability>=0){
		cout << "Insert probability overridden." << endl;
	}
	else{
		m_insertProbability = insertProbability;
	}


}

/**
 * @todo Document this...
 */
/*Network *Eos::getNetwork()
{
	return m_network;
}*/

/**
 * @todo Document this...
 */
/*void Eos::setNetwork(Network *network)
{
	m_network = network;
}*/
